package distribution;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

import utils.FileUtils;

import bbb.sss.Utils;

public class DistributionScheme {

	/**
	 * 获取所有组合
	 * 
	 * @param max
	 * @param count
	 * @return
	 */
	public static List<SchemeItem> allCombination(int max, int count) {
		List<SchemeItem> ac = new ArrayList<SchemeItem>();
		long allCount = Utils.c(max, count);
		for (long code = 1; code <= allCount; code++) {
			ac.add(parse(max, count, code));
		}
		return ac;
	}

	public static List<SchemeItem> firedCombination(int max, int count,
			int firedCount) {
		List<SchemeItem> result = new ArrayList<SchemeItem>();
		List<SchemeItem> ac = allCombination(max, firedCount);
		int leftCount = ac.size();
		int currentIndex = ac.size() - 1;
		SchemeItem currentItem = null;

		while (true) {

			// 吸收当前
			if (currentItem == null) {
				currentItem = merge(ac.get(currentIndex), ac.get(currentIndex));
				ac.remove(currentIndex);
				leftCount--;
			} else {
				if (currentItem.getCount()
						+ differMin(currentItem, ac.get(currentIndex)) <= count) {
					currentItem = merge(currentItem, ac.get(currentIndex));
					ac.remove(currentIndex);
					leftCount--;
				}
			}

			// 结束条件
			if (leftCount == 0) {
				if (currentItem != null) {
					result.add(currentItem);
				}
				break;
			} else {
				currentIndex--;
				// 到达队列末尾时，将当前的加入结果队列，设置当前为空，从头开始
				if (currentIndex == 0) {
					result.add(currentItem);
					currentItem = null;
					currentIndex = ac.size() - 1;
				}
			}
		}
		return result;
	}

	public static List<SchemeItem> firedCombination2(int max, int count,
			int firedCount) {
		List<SchemeItem> result = new ArrayList<SchemeItem>();
		List<SchemeItem> ac = allCombination(max, firedCount);
		int leftCount = ac.size();
		int currentIndex = ac.size() - 1;
		SchemeItem currentItem = null;

		while (true) {
			currentItem = ac.get(currentIndex);
			if (currentItem.getCount()
					+ differMin(currentItem, ac.get(currentIndex)) <= count) {
				currentItem = merge(currentItem, ac.get(currentIndex));
				ac.remove(currentIndex);
				leftCount--;
			}

			// 结束条件
			if (leftCount == 0 || leftCount == 1) {
				if (currentItem != null) {
					result.add(currentItem);
				}
				break;
			} else {
				currentIndex--;
				// 到达队列末尾时，将当前的加入结果队列，设置当前为空，从头开始
				if (currentIndex == 0) {
					result.add(currentItem);
					currentItem = null;
					currentIndex = ac.size() - 1;
				}
			}
		}
		return result;
	}

	/**
	 * 将一个数解析成组合方式
	 * 
	 * @param max
	 * @param count
	 * @param code
	 * @return
	 */
	public static SchemeItem parse(int max, int count, long code) {
		long allCount = Utils.c((long) max, (long) count);
		if (code <= allCount && code > 0) {
			List<Integer> codes = new ArrayList<Integer>();
			Combination.fillListWithNull(codes, count);
			long temp = code - 1;
			int curIndex = count;
			int position = max;
			while (curIndex > 0) {
				if (position > curIndex) {
					long ccc = Utils.c(position - 1, curIndex);
					if (ccc <= temp) {
						temp -= ccc;
						codes.set(curIndex - 1, position);
						curIndex--;
					}
				} else {
					codes.set(curIndex - 1, position);
					curIndex--;
				}
				position--;
			}
			return new SchemeItem(codes);
		}
		return null;
	}

	/**
	 * 将组合方式翻译成数
	 * 
	 * @param max
	 * @param count
	 * @param code
	 * @return
	 */
	public static long format(int max, int count, SchemeItem code) {
		long ret = 1;
		List<Integer> codes = code.getCodes();
		for (int i = count - 1; i >= 0; i--) {
			if (codes.get(i) > i + 1) {
				ret += Utils.c(codes.get(i) - 1, i + 1);
			}
		}
		return ret;
	}

	public static void printSchemeList(List<SchemeItem> sil) {
		if (sil != null && sil.size() > 0) {
			for (SchemeItem si : sil) {
				System.out.println(si);
			}
		}
	}

	public static void saveSchemeList(List<SchemeItem> sil, String filePath) {
		StringBuffer sb = new StringBuffer();
		if (sil != null && sil.size() > 0) {
			for (SchemeItem si : sil) {
				sb.append(si.toString()).append("\r\n");
			}
		}
		FileUtils.writeFile(filePath, sb.toString(), "GBK");
	}

	public static SchemeItem merge(SchemeItem sa, SchemeItem sb) {
		TreeMap<Integer, Integer> mm = new TreeMap<Integer, Integer>();
		if (sa != null && sa.getCodes() != null && sa.getCodes().size() > 0) {
			for (Integer c : sa.getCodes()) {
				mm.put(c, c);
			}
		}
		if (sb != null && sb.getCodes() != null && sb.getCodes().size() > 0) {
			for (Integer c : sb.getCodes()) {
				mm.put(c, c);
			}
		}

		if (mm.size() > 0) {
			List<Integer> codes = new ArrayList<Integer>();
			for (Integer code : mm.keySet()) {
				codes.add(code);
			}
			return new SchemeItem(codes);
		}
		return null;
	}

	public static int differMin(SchemeItem sa, SchemeItem sb) {
		int differ = 0;
		if (sa != null && sb != null && sa.getCount() > 0 && sb.getCount() > 0) {
			SchemeItem siMax = sa.getCount() >= sb.getCount() ? sa : sb;
			SchemeItem siMin = sa.getCount() < sb.getCount() ? sa : sb;

			TreeMap<Integer, Integer> mm = new TreeMap<Integer, Integer>();
			for (Integer c : siMax.getCodes()) {
				mm.put(c, c);
			}

			for (Integer c : siMin.getCodes()) {
				if (mm.get(c) == null) {
					differ++;
				}
			}

		}
		return differ;
	}

	public static int differMax(SchemeItem sa, SchemeItem sb) {
		int differ = 0;
		if (sa != null && sb != null && sa.getCount() > 0 && sb.getCount() > 0) {
			SchemeItem siMax = sa.getCount() >= sb.getCount() ? sa : sb;
			SchemeItem siMin = sa.getCount() < sb.getCount() ? sa : sb;

			TreeMap<Integer, Integer> mm = new TreeMap<Integer, Integer>();
			for (Integer c : siMin.getCodes()) {
				mm.put(c, c);
			}

			for (Integer c : siMax.getCodes()) {
				if (mm.get(c) == null) {
					differ++;
				}
			}

		}
		return differ;
	}

	public static void main(String[] args) {
	}

}
